package com.example.ui.textview;

import android.content.Context;
import android.content.res.Resources;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.method.LinkMovementMethod;
import android.text.style.AbsoluteSizeSpan;
import android.text.style.ClickableSpan;
import android.text.style.ForegroundColorSpan;
import android.text.style.StrikethroughSpan;
import android.text.style.StyleSpan;
import android.text.style.URLSpan;
import android.text.style.UnderlineSpan;
import android.util.DisplayMetrics;
import android.widget.TextView;

import androidx.annotation.ColorInt;

/*
Ex:
TextView tv = findViewById(R.id.tv);
        TextViewBuilder.newInstance(tv)
                .addText("我是第一", Color.BLACK,10)
                .addText("我是第二",Color.GREEN,12)
                .addText("我是第三",Color.YELLOW,6)
                .addText("我是粗体",Color.GRAY,10,true)
                .addText("我是删除",Color.GRAY,12,false,true)
                .addText("我可以点击", Color.GRAY, 12, false, false, new ClickableSpan() {
                    @Override
                    public void onClick(@NonNull View widget) {
                        Toast.makeText(MainActivity.this,"我被点击了",Toast.LENGTH_SHORT).show();
                    }
                })
                .addText("我是链接",Color.BLACK,10,false,false,false,
                        "13872425061", TextViewBuilder.URLType.TEL)
                .setDp(true)
                .build();
 */

public class TextViewBuilder {

    //URL支持的类型
    enum URLType {
        TEL,MAIL,HTTP,SMS,MMS,GEO,NON
    }
    //TextView
    private TextView textView = null;
    //文本内容
    private StringBuilder stringBuilder = null;
    //某段文字的起始位置
    private int[] start_index_text = null;
    //某段文字的结束位置
    private int[] end_index_text = null;
    //某段文字设置的颜色
    private int[] colors = null;
    //某段文字设置的大小 默认是sp  如果使用dp 请调用setDp(true)方法
    private int[] sizes = null;
    //某段文字是否是粗体
    private boolean[] bolds = null;
    //某段文字是否是有下划线
    private boolean[] underlines = null;
    //某段文字是否是带删除线
    private boolean[] deletes = null;
    //某段文字是否为URL 是的话存入  不是存入null
    private String[] URLs = null;
    //某段文字是否为URL 是的话存入URL类型 否则是NON
    private URLType[] urlTypes = null;
    //某段文字是否设置了点击事件 是的话存入事件实例 否则存入null
    private ClickableSpan[] clickableSpans = null;
    //当前文字长度
    private int length = 0;
    //当前文字段数 默认为10  超出时暂时未做处理
    private int index = 0;
    //判断字体大小单位是否为dp
    private boolean isDp = false;

    public static TextViewBuilder newInstance(TextView textView) {
        return new TextViewBuilder(textView, 10);
    }

    public static TextViewBuilder newInstance(TextView textView, int textSize) {
        return new TextViewBuilder(textView, textSize);
    }

    /**
     * 初始化操作
     * @param textView
     * @param textSize
     */
    private TextViewBuilder(TextView textView, int textSize) {
        this.textView = textView;
        stringBuilder = new StringBuilder();
        start_index_text = new int[textSize];
        end_index_text = new int[textSize];
        colors = new int[textSize];
        sizes = new int[textSize];
        bolds = new boolean[textSize];
        underlines = new boolean[textSize];
        deletes = new boolean[textSize];
        urlTypes = new URLType[textSize];
        clickableSpans = new ClickableSpan[textSize];
        URLs = new String[textSize];
    }

    public TextViewBuilder addText(String text) {
        return addText(text, -1, -1, false, false, false, null, URLType.NON, null);
    }

    public TextViewBuilder addText(String text, ClickableSpan clickableSpan) {
        return addText(text, -1, -1, false, false, false, null, URLType.NON, clickableSpan);
    }

    public TextViewBuilder addTextWithColor(String text, @ColorInt int color) {
        return addText(text, color, -1, false, false, false, null, URLType.NON, null);
    }

    public TextViewBuilder addTextWithColor(String text, @ColorInt int color, ClickableSpan clickableSpan) {
        return addText(text, color, -1, false, false, false, null, URLType.NON, clickableSpan);
    }

    public TextViewBuilder addTextWithSize(String text, int textSize) {
        return addText(text, -1, textSize, false, false, false, null, URLType.NON, null);
    }

    public TextViewBuilder addTextWithSize(String text, int textSize, ClickableSpan clickableSpan) {
        return addText(text, -1, textSize, false, false, false, null, URLType.NON, clickableSpan);
    }

    public TextViewBuilder addText(String text, @ColorInt int color, int textSize) {
        return addText(text, color, textSize, false, false, false, null, URLType.NON, null);
    }

    public TextViewBuilder addText(String text, @ColorInt int color, int textSize, ClickableSpan clickableSpan) {
        return addText(text, color, textSize, false, false, false, null, URLType.NON, clickableSpan);
    }

    public TextViewBuilder addText(String text, @ColorInt int color, int textSize, boolean isBold) {
        return addText(text, color, textSize, isBold, false, false, null, URLType.NON, null);
    }

    public TextViewBuilder addText(String text, @ColorInt int color, int textSize, boolean isBold, ClickableSpan clickableSpan) {
        return addText(text, color, textSize, isBold, false, false, null, URLType.NON, clickableSpan);
    }

    public TextViewBuilder addText(String text, @ColorInt int color, int textSize, boolean isBold, boolean isDelete) {
        return addText(text, color, textSize, isBold, isDelete, false, null, URLType.NON, null);
    }

    public TextViewBuilder addText(String text, @ColorInt int color, int textSize, boolean isBold, boolean isDelete, ClickableSpan clickableSpan) {
        return addText(text, color, textSize, isBold, isDelete, false, null, URLType.NON, clickableSpan);
    }

    public TextViewBuilder addText(String text, @ColorInt int color, int textSize, boolean isBold, boolean isDelete, boolean isUnderline) {
        return addText(text, color, textSize, isBold, isDelete, isUnderline, null, URLType.NON, null);
    }

    public TextViewBuilder addText(String text, @ColorInt int color, int textSize, boolean isBold, boolean isDelete, boolean isUnderline, ClickableSpan clickableSpan) {
        return addText(text, color, textSize, isBold, isDelete, isUnderline, null, URLType.NON, clickableSpan);
    }

    public TextViewBuilder addText(String text, @ColorInt int color, int textSize, boolean isBold, boolean isDelete, boolean isUnderline, String URL, URLType urlType) {
        return addText(text, color, textSize, isBold, isDelete, isUnderline, URL, urlType, null);
    }

    /**
     * 添加段落信息
     * @param text
     * @param color
     * @param textSize
     * @param isBold
     * @param isDelete
     * @param isUnderline
     * @param URL
     * @param urlType
     * @param clickableSpan
     * @return
     */
    public TextViewBuilder addText(String text, @ColorInt int color, int textSize, boolean isBold, boolean isDelete, boolean isUnderline, String URL, URLType urlType, ClickableSpan clickableSpan) {
        stringBuilder.append(text);
        start_index_text[index] = length;
        length += text.length();
        end_index_text[index] = length;
        colors[index] = color;
        sizes[index] = textSize;
        bolds[index] = isBold;
        deletes[index] = isDelete;
        underlines[index] = isUnderline;

        URLs[index] = URL;
        if (URL != null) {
            urlTypes[index] = urlType;
        }else {
            urlTypes[index] = URLType.NON;
        }

        if (clickableSpan != null) {
            clickableSpans[index] = clickableSpan;
        }else {
            clickableSpans[index] = null;
        }

        index++;
        return this;
    }

    public TextViewBuilder setDp(boolean dp) {
        isDp = dp;
        return this;
    }

    public void build() {
        String text = stringBuilder.toString();
        SpannableString textSpan = new SpannableString(text);
        for (int i = 0; i < index; i++) {
            //设置颜色
            if (colors[i] != -1) {
                textSpan.setSpan(new ForegroundColorSpan(colors[i]), start_index_text[i], end_index_text[i], Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
            }
            //设置字体大小
            if (sizes[i] != -1) {
                int size = isDp ? dp2sp(sizes[i], this.textView.getContext()) : sizes[i];
                textSpan.setSpan(new AbsoluteSizeSpan(size), start_index_text[i], end_index_text[i], Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
            }
            //设置为粗体
            if (bolds[i]) {
                textSpan.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), start_index_text[i], end_index_text[i], Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
            }
            //设置删除线
            if (deletes[i]) {
                textSpan.setSpan(new StrikethroughSpan(), start_index_text[i], end_index_text[i], Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
            }
            //设置下滑线
            if (underlines[i]) {
                textSpan.setSpan(new UnderlineSpan(), start_index_text[i], end_index_text[i], Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
            }
            //设置链接内容
            if (urlTypes[i] != URLType.NON) {
                String url = null;
                switch (urlTypes[i]) {
                    case GEO:url = "geo:"+URLs[i];break;    // 地图
                    case MMS:url = "mms:"+URLs[i];break;    // 彩信，使用mms:或者mmsto:
                    case SMS:url = "sms:"+URLs[i];break;    // 短信，使用sms:或者smsto:
                    case TEL:url = "tel:"+URLs[i];break;    // 电话
                    case HTTP:url = URLs[i];break;   // 网络
                    case MAIL:url = "mailto:"+URLs[i];break;   // 邮件
                }
                textSpan.setSpan(new URLSpan(url), start_index_text[i], end_index_text[i], Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
            }
            //设置段落点击事件
            if (clickableSpans[i] != null) {
                textSpan.setSpan(clickableSpans[i], start_index_text[i], end_index_text[i], Spanned.SPAN_INCLUSIVE_EXCLUSIVE);//设置点击事件
            }
        }
        this.textView.setText(textSpan);
        //支持超链接和点击事件
        this.textView.setMovementMethod(new LinkMovementMethod());
    }

    /*
    单位装换
     */
    private int dp2sp(int dp, Context context) {
        DisplayMetrics displayMetrics = Resources.getSystem().getDisplayMetrics();
        float fontScale = displayMetrics.scaledDensity;
        return (int) (dp * displayMetrics.density * fontScale + 0.5f);
    }

}
